// Infrastructure/Repositories/RoleRepository.cs
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Domain.Repositories;
using UniversalAdmin.Infrastructure.Data;

namespace UniversalAdmin.Infrastructure.Repositories;

public class RoleRepository : BaseRepository<Role>, IRoleRepository
{
  public RoleRepository(UniversalAdminDbContext context) : base(context) { }

  public async Task<IEnumerable<Role?>> GetByIdsAsync(IEnumerable<int> ids)
  {
    return await _context.Roles
        .Where(r => ids.Contains(r.Id))
        .ToListAsync();
  }

  public async Task<bool> ExistsByNameAsync(string roleName, int excludeRoleId = 0)
  {
    return await _context.Roles
        .AnyAsync(r => r.Name == roleName && r.Id != excludeRoleId);
  }

  public async Task<Role?> GetByNameAsync(string roleName)
  {
    return await _context.Roles
        .FirstOrDefaultAsync(r => r.Name == roleName);
  }

  public async Task<Role?> GetRoleWithUsersAsync(int id)
  {
    return await _context.Roles
        .Include(r => r.UserRoles)
        .ThenInclude(ur => ur.User)
        .FirstOrDefaultAsync(r => r.Id == id);
  }

  public async Task<Role?> GetRoleWithMenusAsync(int id)
  {
    return await _context.Roles
        .Include(r => r.RoleMenus)
        .ThenInclude(rm => rm.Menu)
        .FirstOrDefaultAsync(r => r.Id == id);
  }

  public async Task<(IEnumerable<Role> Items, int TotalCount)> GetPagedRolesAsync(
      string? keyword = null,
      bool? isActive = null,
      int pageIndex = 1,
      int pageSize = 10,
      Expression<Func<Role, bool>>? additionalPredicate = null)
  {
    // 包含关联数据
    var query = _context.Roles
        .Include(r => r.UserRoles)
        .Include(r => r.RoleMenus)
        .ThenInclude(rm => rm.Menu)
        .AsQueryable();

    if (!string.IsNullOrWhiteSpace(keyword))
    {
      var lowerKeyword = keyword.ToLower();
      query = query.Where(r =>
          r.Name.ToLower().Contains(lowerKeyword) ||
          (r.Description != null && r.Description.ToLower().Contains(lowerKeyword)));
    }
    if (isActive.HasValue)
      query = query.Where(r => r.IsActive == isActive.Value);
    if (additionalPredicate != null)
    {
      query = query.Where(additionalPredicate);
    }

    var totalCount = await query.CountAsync();

    var items = await query
        .OrderBy(r => r.Id)
        .Skip((pageIndex - 1) * pageSize)
        .Take(pageSize)
        .AsNoTracking()
        .ToListAsync();

    return (items, totalCount);
  }
  public async Task<bool> ExistsByNameAsync(string roleName, int? excludeRoleId = null)
  {
    return await _context.Roles
        .AnyAsync(r => r.Name == roleName &&
                      (excludeRoleId == null || r.Id != excludeRoleId));
  }

}